﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using BillsPresentation;
using BillsTests.Mocks;
using BillsDomain;

namespace BillsTests
{
    [TestFixture]
    public class PaymentReminderPresenterTests
    {
        [Test]
        public void FutureWeeklyDebitTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Weekly,
                PaymentType = PaymentType.Debit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal amount = testController.ScheduledPayments[0].Amount;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                int week = (i / 7) + 1;
                Assert.AreEqual(week * amount * -1, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }

        [Test]
        public void FutureWeeklyCreditTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Weekly,
                PaymentType = PaymentType.Credit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal amount = testController.ScheduledPayments[0].Amount;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                int week = (i / 7) + 1;
                Assert.AreEqual(week * amount, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }

        [Test]
        public void FutureBiWeeklyDebitTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Biweekly,
                PaymentType = PaymentType.Debit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal amount = testController.ScheduledPayments[0].Amount;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                int biweek = (i / 14) + 1;
                Assert.AreEqual(biweek * amount * -1, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }

        [Test]
        public void FutureBiWeeklyCreditTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Biweekly,
                PaymentType = PaymentType.Credit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal amount = testController.ScheduledPayments[0].Amount;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                int biweek = (i / 14) + 1;
                Assert.AreEqual(biweek * amount, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }

        [Test]
        public void FutureMonthlyDebitTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Monthly,
                PaymentType = PaymentType.Debit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal amount = testController.ScheduledPayments[0].Amount;
            int month = 1;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                if (testView.DaysAndBalances[i].Date.Day == DateTime.Today.Day
                    && testView.DaysAndBalances[i].Date.Month == DateTime.Today.AddMonths(month).Month)
                {
                    month++;
                }

                Assert.AreEqual(month * amount * -1, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }

        [Test]
        public void FutureMonthlyCreditTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Monthly,
                PaymentType = PaymentType.Credit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal amount = testController.ScheduledPayments[0].Amount;
            int month = 1;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                if (testView.DaysAndBalances[i].Date.Day == DateTime.Today.Day
                                    && testView.DaysAndBalances[i].Date.Month == DateTime.Today.AddMonths(month).Month)
                {
                    month++;
                }

                Assert.AreEqual(month * amount, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }

        [Test]
        public void FutureBiMonthlyDebitTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Bimonthly,
                PaymentType = PaymentType.Debit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal amount = testController.ScheduledPayments[0].Amount;
            int bimonth = 1;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                if (testView.DaysAndBalances[i].Date.Day == DateTime.Today.Day
                    && testView.DaysAndBalances[i].Date.Month == DateTime.Today.AddMonths(bimonth * 2).Month)
                {
                    bimonth++;
                }

                Assert.AreEqual(bimonth * amount * -1, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }

        [Test]
        public void FutureBiMonthlyCreditTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Bimonthly,
                PaymentType = PaymentType.Credit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal amount = testController.ScheduledPayments[0].Amount;
            int bimonth = 1;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                if (testView.DaysAndBalances[i].Date.Day == DateTime.Today.Day
                                    && testView.DaysAndBalances[i].Date.Month == DateTime.Today.AddMonths(bimonth * 2).Month)
                {
                    bimonth++;
                }

                Assert.AreEqual(bimonth * amount, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }

        [Test]
        public void FutureOneWeeklyOneBiWeeklyCreditTwoFifty()
        {
            TestController testController = new TestController();
            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Weekly,
                PaymentType = PaymentType.Credit,
                IncludeInProjection = true
            });

            testController.ScheduledPayments.Add(new ScheduledPayment()
            {
                Amount = 2.5M,
                FirstDate = DateTime.Today,
                Id = 1,
                PaymentRecurrence = Recurrence.Biweekly,
                PaymentType = PaymentType.Credit,
                IncludeInProjection = true
            });

            TestView testView = new TestView() { CurrentBalance = 0.0M, DayOnCalendar = DateTime.Today, AsOfDay = DateTime.Today };
            PaymentReminderPresenter presenter = new PaymentReminderPresenter(testView, testController);
            testView.RaiseLoad();
            Assert.AreEqual(90, testView.DaysAndBalances.Count);
            decimal weeklyAmount = testController.ScheduledPayments[0].Amount;
            decimal biweeklyAmount = testController.ScheduledPayments[1].Amount;
            for (int i = 0; i < 90; i++)
            {
                Assert.AreEqual(DateTime.Today.AddDays(i), testView.DaysAndBalances[i].Date);
                int week = i / 7 + 1;
                int biweek = i / 14 + 1;
                Assert.AreEqual(week * weeklyAmount + biweek * biweeklyAmount, testView.DaysAndBalances[i].EndOfDayBalance);
            }
        }
    }
}
